// Test.hpp
//
// This file contains the Test class along with the macros which make effective
// in the harness.
//

#ifndef TEST_H
#define TEST_H
#if 0
#include <exception>
#endif

// ??? Не совсем понятно поведение
#define RETURN_ENABLE 0
#define UTEST_THRESHOLD 0.001

#include "SimpleString.hpp"

class TestResult;



class Test
{
public:
    Test (const SimpleString& testName);

    virtual void    run (TestResult& result) = 0;

    void            setNext(Test *test);
    Test            *getNext () const;

protected:

    bool check (long expected, long actual, TestResult& result, const SimpleString& fileName, long lineNumber);
    bool check (const SimpleString& expected, const SimpleString& actual, TestResult& result, const SimpleString& fileName, long lineNumber);

    SimpleString    name_;
    Test            *next_;

};

#define FAIL(text) \
{ result_.addFailure (Failure (name_, __FILE__, __LINE__,(text))); return; }

#define TEST(groupName, testName)\
class groupName##testName##Test : public Test \
{\
public: \
    groupName##testName##Test () : Test ("Test_" #groupName "_" #testName) {} \
    void run (TestResult& result_); \
} groupName##testName##TestInstance;\
void groupName##testName##Test::run (TestResult& result_)


#define CHECK(condition)\
{ \
  if ((condition)) \
  { \
    if (RETURN_ENABLE) return; \
  } \
  else \
    result_.addFailure (Failure (name_, __FILE__,__LINE__, #condition)); \
}


#define CHECK_EQUAL(expected,actual)\
{ if ((expected) == (actual)) {if (RETURN_ENABLE) return;} else result_.addFailure(Failure(name_, __FILE__, __LINE__, StringFrom(expected), StringFrom(actual))); }

#define LONGS_EQUAL(expected,actual)\
{ long actualTemp = actual; \
  long expectedTemp = expected; \
  if ((expectedTemp) != (actualTemp)) \
{ result_.addFailure (Failure (name_, __FILE__, __LINE__, StringFrom(expectedTemp), \
StringFrom(actualTemp))); else if (RETURN_ENABLE) return; } }

#define DOUBLES_EQUAL(expected,actual,threshold)\
{ double actualTemp = actual; \
  double expectedTemp = expected; \
  if (fabs ((expectedTemp)-(actualTemp)) > threshold) \
 result_.addFailure (Failure (name_, __FILE__, __LINE__, \
StringFrom((double)expectedTemp), StringFrom((double)actualTemp))); else if (RETURN_ENABLE) return; }

#if 0
#define EXCEPTION_CATCH(x, e)\
  try{x; FAIL(#e " must occure");} catch(e) {}
#endif

#endif

